import { _decorator, instantiate, ProgressBar, tween, Tween, Vec3 } from 'cc'
import { EntityManager } from '../../Base/EntityManager'
import { EntityTypeEnum, IActor, InputTypeEnum, toFixed } from '../../Common'
import { EntityStateEnum, EventEnum } from '../../Enum'
import DataManager from '../../Global/DataManager'
import EventManager from '../../Global/EventManager'
import { rad2Angle } from '../../Utils'
import { WeaponManager } from '../Weapon/WeaponManager'
import { ActorStateMachine } from './ActorStateMachine'
const { ccclass } = _decorator

@ccclass('ActorManager')
export class ActorManager extends EntityManager {
  id: number
  bulletType: EntityTypeEnum
  private wm: WeaponManager
  private hp: ProgressBar
  private targetPos: Vec3
  private tw: Tween<unknown>

  init(data: IActor) {
    this.hp = this.node.getComponentInChildren(ProgressBar)
    this.id = data.id
    this.fsm = this.addComponent(ActorStateMachine)
    this.fsm.init(data.type)
    this.state = EntityStateEnum.Idle
    this.bulletType = data.bulletType
    // 初始化时位置在（0,0）,后端传过来的位置在（-150, -150），先隐藏,避免闪烁问题
    this.node.active = false
    this.targetPos = undefined

    const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Weapon1)
    const weapon = instantiate(prefab)
    weapon.setParent(this.node)
    this.wm = weapon.addComponent(WeaponManager)
    this.wm.init(data)
  }

  tick(dt: number) {
    if (this.id !== DataManager.Instance.myPlayerId) return
    // 如果玩家正在操作摇杆
    if (DataManager.Instance.jm.input.length() > 0) {
      const { x, y } = DataManager.Instance.jm.input
      EventManager.Instance.emit(EventEnum.ClientSync, {
        id: DataManager.Instance.myPlayerId,
        type: InputTypeEnum.ActorMove,
        direction: {
          x: toFixed(x),
          y: toFixed(y)
        },
        dt: toFixed(dt)
      })
    }
  }

  render(data: IActor) {
    this.renderPosition(data)
    this.renderDirection(data)
    this.renderHP(data)
  }

  renderPosition(data: IActor) {
    const { position } = data
    const newPos = new Vec3(position.x, position.y)
    if (!this.targetPos) {
      this.node.setPosition(newPos)
      this.targetPos = newPos
      this.node.active = true
    } else if (!this.targetPos.equals(newPos)) {
      // 因为newPos是后端传过来的，后端每隔100ms传一次，加这个判断是让这个renderPositon100ms执行一次
      this.tw?.stop()
      this.node.setPosition(this.targetPos)
      this.targetPos.set(newPos)
      this.state = EntityStateEnum.Run
      this.tw = tween(this.node)
        .to(0.1, { position: this.targetPos })
        .call(() => {
          this.state = EntityStateEnum.Idle
        })
        .start()
    }
  }

  renderDirection(data: IActor) {
    const { direction } = data

    // 翻转人物，但不翻转血条
    if (direction.x !== 0) {
      this.node.setScale(direction.x > 0 ? 1 : -1, 1)
      this.hp.node.setScale(direction.x > 0 ? 1 : -1, 1)
    }

    // 计算武器朝向
    const side = Math.sqrt(direction.x ** 2 + direction.y ** 2) // 斜边的长度
    const rad = Math.asin(direction.y / side) // Y轴与斜边的夹角（单位：弧度）
    const angle = rad2Angle(rad)
    // 以Z轴为旋转轴，旋转角度angle
    this.wm.node.setRotationFromEuler(0, 0, angle)
  }

  renderHP(data: IActor) {
    // 渲染血条
    this.hp.progress = data.hp / this.hp.totalLength
  }
}
